//
//  MainViewController.swift
//  WBDemo
//
//  Created by Meng on 16/12/14.
//  Copyright © 2016年 demo. All rights reserved.
//

import UIKit

class MainViewController: UITabBarController {

    enum MyError: Error {
        case jsonPathError // json路径错误
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        // iOS7以后只需要设置tintColor, 那么图片和文字都会按照tintColor渲染
        tabBar.tintColor = UIColor.orange
        
//        // 添加子控制器
//        addChildViewControllers()
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tabBar.addSubview(composeButton)
//        MYLog(composeButton.frame)
        composeButton.center = CGPoint(x: tabBar.center.x, y: composeButton.frame.size.height * 0.5)
    }
    
    // MARK: - 添加所有控制器
    
    private func addChildViewControllers() {
        
        /*
         Swift和OC不太一样, OC中一般情况如果发生错误会给传入的指针赋值, 而在Swift中使用的是异常处理机制
         1.以后但凡看大 throws的方法, 那么就必须进行 try处理, 而只要看到try, 就需要写上do catch
         2.do{}catch{}, 只有do中的代码发生了错误, 才会执行catch{}中的代码
         3. try  正常处理异常, 也就是通过do catch来处理
         try! 告诉系统一定不会有异常, 也就是说可以不通过 do catch来处理
         但是需要注意, 开发中不推荐这样写, 一旦发生异常程序就会崩溃
         如果没有异常那么会返回一个确定的值给我们
         
         try? 告诉系统可能有错也可能没错, 如果没有系统会自动将结果包装成一个可选类型给我们, 如果有错系统会返回nil, 如果使用try? 那么可以不通过do catch来处理
         */
        do {
            // 解析json数据
            guard let filePath = Bundle.main.path(forResource: "MainVCSettings", ofType: "json") else {
                MYLog("json路径错误")
                throw MyError.jsonPathError
            }
            
//            MYLog(filePath)
            
            let url = URL.init(fileURLWithPath: filePath)
//            MYLog(url)
            
            let data = try Data(contentsOf: url)
//            MYLog(str)
            
            let dictArray = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! [[String : AnyObject]]
//            MYLog(dictArray)
            
            for dict in dictArray {
                let vcName = dict["vcName"] as? String
                let title = dict["title"] as? String
                let imageName = dict["imageName"] as? String
                addChildViewController(vcName, title: title, imageName: imageName)
            }
            
        } catch {
            
            MYLog("json解析失败")
            addChildViewController("HomeTableViewController", title: "首页", imageName: "tabbar_home")
            addChildViewController("MessageTableViewController", title: "消息", imageName: "tabbar_message_center")
            addChildViewController("NullViewController", title: "", imageName: "")
            addChildViewController("DiscoverTableViewController", title: "发现", imageName: "tabbar_discover")
            addChildViewController("ProfileTableViewController", title: "我", imageName: "tabbar_profile")
            
        }
        
        
    }
    /*
     public : 最大权限, 可以在当前framework和其他framework中访问
     internal : 默认的权限, 可以在当前framework中随意访问
     private : 私有权限, 只能在当前文件中访问
     以上权限可以修饰属性/方法/类
     
     在企业开发中建议严格的控制权限, 不想让别人访问的东西一定要private
     */
    private func addChildViewController(_ childControllerName: String?, title: String?, imageName: String?) {
        
        // <ÂæÆÂçöDemo.HomeTableViewController: 0x787937c0>
        // 获取命名空间 ÂæÆÂçöDemo
        guard let name = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String else {
//            MYLog(name!)
            MYLog("获取命名空间失败")
            return
        }
        guard let vcName = childControllerName else {
            MYLog("VCName为空")
            return
        }
        let clsName = name + "." + vcName
        // 根据字符串获取class
        let cls : AnyClass? = NSClassFromString(clsName)
//        MYLog(cls)
        // 根据class创建对象
        // 创建对象前需要确定具体类型
        guard let type = cls as? UITableViewController.Type else {
//            MYLog(type)
            MYLog("转换具体类型失败")
            return
        }
        // 创建对象
        let vc = type.init()
//        MYLog(vc)
        
        guard let imgName = imageName else {
            MYLog("imageName为空")
            return
        }
        
        let imgName1 = imgName as NSString
        
        if imgName1.length > 0 {
            vc.tabBarItem.image = UIImage(named: imgName)
            vc.tabBarItem.selectedImage = UIImage(named: imgName + "_highlighted")
        }
        
        vc.title = title
        let navi = UINavigationController(rootViewController: vc)
        addChildViewController(navi)
        
    }
    
    // MARK: - 懒加载
    private lazy var composeButton: UIButton = { () -> UIButton in
        let button = UIButton(imageName: "tabbar_compose_icon_add", backgroundImageName: "tabbar_compose_button")
        
        button.addTarget(self, action: #selector(composeButtonClick(btn:)), for: UIControlEvents.touchUpInside)
        
        return button
    }()
    // 如果给按钮的监听方法加上private就会报错, 报错原因是因为监听事件是由运行循环触发的, 而如果该方法是私有的只能在当前类中访问
    // 而相同的情况在OC中是没有问题, 因为OC是动态派发的
    // 而Swift不一样, Swift中所有的东西都在是编译时确定的
    // 如果想让Swift中的方法也支持动态派发, 可以在方法前面加上 @objc
    // 加上 @objc就代表告诉系统需要动态派发
    @objc private func composeButtonClick(btn: UIButton) {
        let sb = UIStoryboard.init(name: "Compose", bundle: nil)
        guard let vc = sb.instantiateInitialViewController() else {
            return
        }
        present(vc, animated: true, completion: nil)
    }
    

}
